/*
 *  PClassRegistry.h
 *  
 *
 *  Created by Peter on 23.02.12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef PCLASS_REGISTRY_H
#define PCLASS_REGISTRY_H

#include "AObject.h"

#include <map>
#include <iostream>

/*
 * This registry keeps track of all classes that can be dynamically instantiated based
 * on their class id when they come up in files.
 *
 * The interface doesn't have much to do with Avid's, but that's not necessary. This is
 * just here to get the job done.
 *
 * TODO: Store the full class name in there somewhere 
 */
class PClassRegistry
{	
	
public:
	
	// Register a class with the registry. It needs to be derived from AObject and
	// it needs to have the A_DECLARE_CLASS macro in the class definition.
	// You can use this function like so: PClassRegistry::registerClass< AMyClass >();
	// I'm sure Avid's version isn't this fancy :)
	template< class C >
	static void registerClass();
	
	// Returns true if there is a class with the given PCID
	static bool isClassRegistered( AObject::PCID pcid );
	
	// Returns a new instance of the given type. The corresponding class ID needs to
	// have been registered before of course.
	static AObject* createInstance( AObject::PCID classId );
	
	// Dump the information in the class registry to a stream for debugging purposes
	static void dump( std::ostream& str );
	
protected:
	
	// Function pointer type for factory functions
	typedef AObject* (*FactoryFunc)();
	
	typedef std::map< AObject::PCID, FactoryFunc > ClassRegistryMap;
	typedef ClassRegistryMap::value_type           ClassRegistryMapItem;
	
	// This is the factory function we use by default
	template< typename T > static AObject* objectFactory()
	{
		return new T;
	};
	
	static ClassRegistryMap _classes;
	
};

template< class C >
void PClassRegistry::registerClass()
{
	_classes.insert (
		ClassRegistryMapItem ( 
			  C::_pcid,
			  &objectFactory< C >
		)
	);
}

#endif /*Inclusion Guard*/